/******************************************************************************
 *                                                                            *
 *               (c) 2008-2009 HutLab. All rights reserved.                   *
 *                        Eduardo Henrique Leite                              *
 *                                                                            *
 ******************************************************************************

 History:
 Created 01/01/2009

 */

package hutlab.sudoku.engine.ui;

import javax.microedition.lcdui.*;
import hutlab.sudoku.engine.base.*;

/**
 * Game menu class.
 */
public class Menu extends GameObject{

    // ----- FIELDS -----

    private ArrayList mItems;
    private int mActiveIndex = 0;
    private boolean mCentred;
    private Font mFont;
    private Font mActiveFont;
    private ColourRGB mColour;
    private ColourRGB mActiveColour;

    // ----- GETTERS -----

    /**
     * Returns menu items list.
     */
    public ArrayList getItems(){
        return mItems;
    }

    /**
     * Returns whether the menu items are marked to be rendered centred
     * onto the screen.
     */
    public boolean getCentred(){
        return mCentred;
    }

    /**
     * Returns the font the menu items will be rendered.
     */
    public Font getFont(){
        return mFont;
    }

    /**
     * Returns the font the active menu item will be rendered.
     */
    public Font getActiveFont(){
        return mActiveFont;
    }

    /**
     * Returns the colour the menu items will be rendered.
     */
    public ColourRGB getColour(){
        return mColour;
    }

    /**
     * Returns the colour the active menu item will be rendered.
     */
    public ColourRGB getActiveColour(){
        return mActiveColour;
    }

    /**
     * Returns the active menu item index.
     */
    public int getActiveIndex(){
        return mActiveIndex;
    }

    // ----- SETTERS -----

    /**
     * Sets whether the menu items will be rendered centred onto the screen.
     */
    public void setCentred(boolean centred){
        mCentred = centred;
    }

    /**
     * Sets the menu items list.
     */
    public void setItems(ArrayList items){
        mItems = items;
    }

    /**
     * Sets the font the menu items will be rendered.
     */
    public void setFont(Font font){
        mFont = font;
    }

    /**
     * Sets the font the active menu item will be rendered.
     */
    public void setActiveFont(Font font){
        mActiveFont = font;
    }

    /**
     * Sets the colour the menu items will be rendered.
     */
    public void setColour(ColourRGB colour){
        mColour = colour;
    }

    /**
     * Sets the colour the active menu item will be rendered.
     */
    public void setActiveColour(ColourRGB colour){
        mActiveColour = colour;
    }

    /**
     * Sets the active menu item index.
     */
    public void setActiveIndex(int index){
        ((MenuItem) this.mItems.getElement(this.mActiveIndex)).setActive(false);
        ((MenuItem) this.mItems.getElement(index)).setActive(true);
        mActiveIndex = index;
    }

    // ----- CONSTRUCTOR -----

    /**
     * Creates a new Menu object.
     */
    public Menu(){
        this.mItems = new ArrayList();
    }

    // ----- PUBLIC -----

    /**
     * Renders the object onto the screen.
     */
    public void render(Graphics graphics){
        if (!validateData()){
            return;
        }

        activeDefault();
        
        int x = this.getX();
        int y = this.getY();
        int betweenLines = 20; // Calculate this later

        MenuItem currentItem = null;
        for (int i=0; i<this.mItems.getCount(); i++){
            currentItem = (MenuItem) this.mItems.getElement(i);
            renderItem(graphics, currentItem, x, y);

            y+= betweenLines;
        }
    }

    /**
     * Handles keyboard event.
     */
    public int keyCommand (int keyCode){
        int selectedIndex = -1;

        switch (keyCode){
            case SUDOKU_KEY_UP:
                moveUp();
                break;
            case SUDOKU_KEY_DOWN:
                moveDown();
                break;
            case SUDOKU_KEY_OK:
                selectedIndex = this.mActiveIndex;
                break;
        }

        return selectedIndex;
    }

    // ----- PRIVATE -----

    /**
     * Validates data for rendering.
     */
    private boolean validateData(){
        boolean isValid = true;

        if (this.mColour == null
            || this.mFont == null
            || this.mItems == null){
            isValid = false;
        }

        return isValid;
    }

    /**
     * Checks active menu items default values.
     */
    private void activeDefault(){
        if (this.mActiveColour == null){
            this.mActiveColour = this.mColour;
        }

        if (this.mActiveFont == null){
            this.mActiveFont = this.mFont;
        }
    }

    /**
     * Renders the menu item.
     */
    private void renderItem(Graphics graphics, MenuItem item, int x, int y){
        int red, green, blue, anchor;
        Font font;

        if (item.getActive()){
            red = this.mActiveColour.getRed();
            green = this.mActiveColour.getGreen();
            blue = this.mActiveColour.getBlue();

            font = this.mActiveFont;
        }
        else {
            red = this.mColour.getRed();
            green = this.mColour.getGreen();
            blue = this.mColour.getBlue();

            font = this.mFont;
        }

        anchor = (this.mCentred ? Graphics.TOP | Graphics.HCENTER : Graphics.TOP | Graphics.LEFT);

        graphics.setFont(font);
        graphics.setColor(red, green, blue);
        graphics.drawString(item.getText(), x, y, anchor);
    }

    /**
     * Moves the menu selection down.
     */
    private void moveDown(){
        if (this.mActiveIndex >= this.mItems.getCount() - 1){
            this.setActiveIndex(0);
        }
        else {
            this.setActiveIndex(this.mActiveIndex + 1);
        }
    }

    /**
     * Moves the menu selection up.
     */
    private void moveUp(){
        if (this.mActiveIndex <= 0){
            this.setActiveIndex(this.mItems.getCount() - 1);
        }
        else {
            this.setActiveIndex(this.mActiveIndex - 1);
        }
    }
}
